/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is Forte for Java, Community Edition. The Initial * Developer of the Original Code is Sun Microsystems, Inc. Portions * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved. */ package org.netbeans.core; import java.io.*; import java.util.*; import java.net.*; import org.xml.sax.*; import org.xml.sax.helpers.*; import org.openide.TopManager; import org.openide.NotifyDescriptor; import org.openide.util.HelpCtx; /** Reference implementation of the helpfiles of JavaHelp. * Also holds all installed helpIDs and can display a * help page when such HelpCtx should be opened. * * @author Jaroslav Tulach */ public abstract class Help extends Object { private Help () {} /** instance of the Help */ private static Impl help; /** Finds default instance of the help. */ public static Impl getDefault () { if (help == null) { try { Class.forName ("javax.help.HelpSet"); // NOI18N try { // Avoid making any static references to javax.help.* // (just new JavaHelp() should work, but this is a little safer): help = (Impl) Class.forName ("org.netbeans.core.JavaHelp").newInstance (); // NOI18N } catch (Exception e) { // These would actually be unexpected. TopManager.getDefault ().notifyException (e); help = new XMLImpl (); } } catch (ClassNotFoundException cnfe) { // Fine, JavaHelp not installed. help = new XMLImpl (); } } return help; } /** Methods delegated to different implementations. */ public static interface Impl { /** Adds help set URL into the system */ public void addHelpSet (URL resource, String moduleCodeName, String moduleDisplayName); /** Removes help set URL from the system */ public void removeHelpSet (URL resource); /** Shows help. */ public void showHelp (HelpCtx ctx); /** Get a map from module code names to home IDs. */ public Map getHomesByCode (); /** Get a map from module display names to home IDs. */ public Map getHomesByDisplay (); /** Display name for the master index, or <code>null</code> if none. */ public String getMasterDisplayName (); /** Help ID for the master index, or <code>null</code> if none. */ public String getMasterID (); /** Test whether a given homeID is particularly distinguished, so should be displayed first. * @param id the home ID * @return true if it should be considered distinguished */ public boolean isDistinguished (String homeID); } /** Simple implementation that takes only important tags from the HelpSet file. * Serves for two purposes: * <OL> * <LI>Implementation of Help.Impl * <LI>DocumentHandler callback for XML * </OL> */ private static final class XMLImpl extends HandlerBase implements Impl { /** tags in map file */ private static final String MAP_ID = "mapID"; // NOI18N private static final String TARGET = "target"; // NOI18N private static final String URL = "url"; // NOI18N /** important tags in help set file */ private static final String MAPS = "maps"; // NOI18N private static final String HOME_ID = "homeID"; // NOI18N private static final String MAPREF = "mapref"; // NOI18N private static final String LOCATION = "location"; // NOI18N // [PENDING] these should not be static--this class should be // untangled so they do not have to be /** map of URL of help set to map of string ids to string URLs. * Type (URL, Map (String, String)). * @associates HashMap */ private static Map help = new HashMap (7); /** map of helpset URLs to code names * @associates String*/ private static Map moduleCodeNames = new HashMap (); // Map<URL, String> /** map of helpset URLs to display names * @associates String*/ private static Map moduleDisplayNames = new HashMap (); // Map<URL, String> /** map of code names to home IDs * @associates String*/ private static Map homesByCode = new HashMap (); // Map<String, String> /** map of display names to home IDs * @associates String*/ private static Map homesByDisplay = new HashMap (); // Map<String, String> public synchronized Map getHomesByCode () { return new HashMap (homesByCode); } public synchronized Map getHomesByDisplay () { return new HashMap (homesByDisplay); } /** buffer to contain the homeID or null if we are not reading homeID */ private StringBuffer homeID; /** base URL for parsing file */ private URL base; private Parser parser; /** map to currently work with (String, String) * @associates String*/ private Map current; /** module info to currently work with */ private String moduleCodeName, moduleDisplayName; /** Creates new XML parser/saver for HelpSet file. * This constructor is for the */ public XMLImpl () { } /** Creates new XML parser/saver for HelpSet file. */ private XMLImpl (URL base, Map current, String moduleCodeName, String moduleDisplayName) { this.base = base; this.current = current; this.moduleCodeName = moduleCodeName; this.moduleDisplayName = moduleDisplayName; parser = org.openide.loaders.XMLDataObject.createParser (); parser.setDocumentHandler (this); } // [PENDING] synchronized?? /** Adds help set URL into the system */ public void addHelpSet (URL resource, String moduleCodeName, String moduleDisplayName) { //System.err.println ("Adding help set: " + resource + " " + moduleCodeName + " " + moduleDisplayName); try { HashMap map = new HashMap (); XMLImpl xml = new XMLImpl (resource, map, moduleCodeName, moduleDisplayName); xml.parse (); // store the map help.put (resource, map); moduleCodeNames.put (resource, moduleCodeName); moduleDisplayNames.put (resource, moduleDisplayName); } catch (SAXException e) { TopManager.getDefault ().notifyException (e); } catch (IOException e) { TopManager.getDefault ().notifyException (e); } } /** Removes help set URL from the system */ public synchronized void removeHelpSet (URL resource) { help.remove (resource); homesByCode.remove (moduleCodeNames.remove (resource)); homesByDisplay.remove (moduleDisplayNames.remove (resource)); } /** Shows help. */ public synchronized void showHelp (HelpCtx ctx) { URL url = ctx.getHelp (); String s = ctx.getHelpID (); if (url == null) { // iterator over maps String x = null; Iterator it = help.values ().iterator (); while (x == null && it.hasNext ()) { Map m = (Map)it.next (); x = (String)m.get (s); } if (x != null) { try { url = new URL (x); } catch (MalformedURLException e) { // go on, but it should not happen } } } if (url != null) { TopManager.getDefault ().showUrl (url); } else { TopManager.getDefault ().notify (new NotifyDescriptor.Message (Main.getString ("EXC_HelpIDNotFound", s))); } } /** Registration of the id */ private void registerID (String id, URL url) { // saving the URL as strings could save some memory current.put (id.intern (), url.toExternalForm ().intern ()); } /** If we have homeID buffer non-null we add the text to it. * Because it composes the homeID. */ public void characters(char[] ch, int start, int length) throws SAXException { if (homeID != null) { homeID.append (ch, start, length); } } /** Accepts module item */ public void startElement (String name, AttributeList attr) throws SAXException { if (MAP_ID.equals (name)) { String target = attr.getValue (TARGET); String url = attr.getValue (URL); if (target != null && url != null) { try { registerID (target, new URL (base, url)); } catch (MalformedURLException e) { throw new SAXException ("Malformed help URL: " + url + " for target: " + target); // NOI18N } } return; } if (HOME_ID.equals (name)) { homeID = new StringBuffer (); return; } if (MAPREF.equals (name)) { processMap (attr.getValue (LOCATION)); return; } } /** Accepts module item */ public void endElement (String name) { if (HOME_ID.equals (name)) { String id = homeID.toString (); //System.err.println ("Found home ID: " + id + " " + moduleCodeName + " " + moduleDisplayName); homesByCode.put (moduleCodeName, id); homesByDisplay.put (moduleDisplayName, id); homeID = null; } } /** Processes map file. */ private void processMap (String url) throws SAXException { try { URL map = new URL (base, url); XMLImpl impl = new XMLImpl (map, current, moduleCodeName, moduleDisplayName); impl.parse (); } catch (IOException e) { throw new SAXException (e.getMessage ()); } } /** Parses the HelpSet file. */ public void parse () throws IOException, SAXException { parser.parse (base.toExternalForm ()); } /** Display name for the master index, or <code>null</code> if none. */ public String getMasterDisplayName() { return null; } /** Help ID for the master index, or <code>null</code> if none. */ public String getMasterID() { return null; } /** Test whether a given homeID is particularly distinguished, so should be displayed first. * @param id the home ID * @return true if it should be considered distinguished */ public boolean isDistinguished(String homeID) { return false; } } } /* * Log * 12 Gandalf 1.11 1/13/00 Jaroslav Tulach I18N * 11 Gandalf 1.10 12/21/99 Jesse Glick Putting User's Guide off * from the rest of the help menu items to visually distinguish it. * 10 Gandalf 1.9 12/20/99 Jesse Glick Reorganized Help | * Features to be Help | Documentation, killing old UG browse action, * better labelling of master help set, etc. * 9 Gandalf 1.8 10/22/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems Copyright in File Comment * 8 Gandalf 1.7 10/1/99 Libor Kramolis * 7 Gandalf 1.6 10/1/99 Libor Kramolis * 6 Gandalf 1.5 9/29/99 Jesse Glick Safer test-loading of * JavaHelp impl. * 5 Gandalf 1.4 9/27/99 Jesse Glick JavaHelp implementation * (optional). * 4 Gandalf 1.3 7/9/99 Jesse Glick ModuleHelpAction * implemented. * 3 Gandalf 1.2 6/25/99 Jaroslav Tulach Works with IBM parser. * 2 Gandalf 1.1 6/8/99 Ian Formanek ---- Package Change To * org.openide ---- * 1 Gandalf 1.0 5/7/99 Jaroslav Tulach * $ */